import React, { useEffect, useState, useRef } from "react";
import classNames from "classnames";
interface DrawerOptionsT {
  visible?: boolean; // 抽屉是否显示
  position?: "bottom" | "top" | "left" | "right"; // 指定弹出位置
  children?: React.ReactNode; // 内容
  mask?: boolean; // 是否展示遮罩
  maskClosable?: boolean; // 是否允许背景点击
  destroyOnClose?: boolean; // 抽屉不可见时卸载内容
  maskClassName?: string; // 遮罩类名，不会覆盖组件原本样式，加 !important 可覆盖
  bodyClassName?: string; // 内容区域类名，不会覆盖组件原本样式，加 !important 可覆盖
  bodyStyle?: React.CSSProperties;
  onClose?: () => void; // 关闭时触发
}

/** 动画时间，单位（ms） */
const animationTime = 300;
/** 淡入动画效果 */
const appearAnimation = [{ opacity: 0 }, { opacity: 1 }];
/** 淡出动画效果 */
const disappearAnimation = [{ opacity: 1 }];

const Drawer: React.FC<DrawerOptionsT> = (props) => {
  const [firstLoaded, setFirstLoaded] = useState(false); // 是否第一次加载
  const [action, setAction] = useState<"appear" | "disappear">("appear");
  const options: DrawerOptionsT = props;
  const drawerMaskRef = useRef<HTMLDivElement | null>();
  useEffect(() => {
    if (!drawerMaskRef.current) return;
    const maskDom = drawerMaskRef.current;
    if (options.visible) {
      setAction("appear");
      document.body.style.overflow = "hidden";
      maskDom.style.visibility = "inherit";
      maskDom.animate(appearAnimation, animationTime);
      document.body.appendChild(maskDom);
    } else {
      setAction("disappear");
      maskDom.animate(disappearAnimation, animationTime).onfinish = () => {
        document.body.style.overflow = "auto";
        maskDom.style.visibility = "hidden";
        if (options.destroyOnClose) {
          maskDom.remove();
        }
      };
    }
  }, [options.visible]);

  useEffect(() => {
    if (!firstLoaded && options.visible) {
      setFirstLoaded(true);
    }
  }, [options.visible]);

  if (!firstLoaded && !options.visible) {
    return null;
  }
  return (
    <div
      ref={(ref) => (drawerMaskRef.current = ref)}
      className={classNames("mask", options.maskClassName)}
    >
      <div
        style={options.bodyStyle}
        className={classNames(
          "drawer",
          `drawer-${options.position}`,
          `drawer-${options.position}-${action}`,
          options.bodyClassName
        )}
      >
        <div className={classNames("drawer-content")}>{options.children}</div>
      </div>
    </div>
  );
};

export default Drawer;
